package plugin

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
)

func Writefile(id string ,key string)(string,error){
    // filename := "/tmp/%d",id
    filename := fmt.Sprintf("/tmp/%d",id)
	err := ioutil.WriteFile(filename, []byte(key), 0644)
	if err != nil {
		log.Println("写入文件失败:", err)
		return "",err
	}
    return filename,nil
}

//RSA公钥私钥产生
func GenRsaKey() (prvkey, pubkey []byte) {
    // 生成私钥文件
    privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
    if err != nil {
        panic(err)
    }
    derStream := x509.MarshalPKCS1PrivateKey(privateKey)
    block := &pem.Block{
        Type:  "RSA PRIVATE KEY",
        Bytes: derStream,
    }
    prvkey = pem.EncodeToMemory(block)
    publicKey := &privateKey.PublicKey
    derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
    if err != nil {
        panic(err)
    }
    block = &pem.Block{
        Type:  "PUBLIC KEY",
        Bytes: derPkix,
    }
    pubkey = pem.EncodeToMemory(block)
    return
}

func DefaultRsa()([]byte,[]byte){
    prvkey,errprv:= ioutil.ReadFile("default.prvkey.pem")
    pubkey,errpub:= ioutil.ReadFile("default.pubkey.pem")
    if errprv != nil{
        panic(errprv.Error())
    }
    if errpub != nil{
        panic(errpub.Error())
    }
    return prvkey,pubkey
}

//签名
func RsaSignWithSha256(data []byte, keyBytes []byte) []byte {
    h := sha256.New()
    h.Write(data)
    hashed := h.Sum(nil)
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("private key error"))
    }
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        log.Println("ParsePKCS8PrivateKey err", err)
        panic(err)
    }

    signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
    if err != nil {
        fmt.Printf("Error from signing: %s\n", err)
        panic(err)
    }

    return signature
}

//验证
func RsaVerySignWithSha256(data, signData, keyBytes []byte) bool {
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("public key error"))
    }
    pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }

    hashed := sha256.Sum256(data)
    err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], signData)
    if err != nil {
        panic(err)
    }
    return true
}

// 公钥加密
func RsaEncrypt(data, keyBytes []byte) []byte {
    //解密pem格式的公钥
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("public key error"))
    }
    // 解析公钥
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    // 类型断言
    pub := pubInterface.(*rsa.PublicKey)
    //加密
    ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, pub, data)
    if err != nil {
        panic(err)
    }
    return ciphertext
}


// 私钥解密
func RsaDecrypt(ciphertext, keyBytes []byte) []byte {
    //获取私钥
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("private key error!"))
    }
    //解析PKCS1格式的私钥
    priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    // 解密
    data, err := rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
    if err != nil {
        panic(err)
    }
    return data
}

func EncryptCtx(pubKey string,prvKey string,data []byte)(string,string){
    signData := RsaSignWithSha256([]byte(data), []byte(prvKey))
    checkCode := RsaVerySignWithSha256([]byte(data), signData, []byte(pubKey))
    if checkCode{
        ciphertext := RsaEncrypt([]byte(data), []byte(pubKey))
        // singd := hex.EncodeToString(signData)
        // log.Println(hex.EncodeToString(signData),signData)
        // xx,err := hex.DecodeString(singd)
        // if err != nil{
        //     log.Println(xx)
        // }
        // log.Println(xx)
        // log.Println(hex.EncodeToString(signData),string(signData))
        return hex.EncodeToString(ciphertext),hex.EncodeToString(signData)
    }else{
        message := "签名校验失败"
        log.Println(message)
        return "",""
    }

}

//prvKey, pubKey := GenRsaKey() 生成公钥 私钥
// signData := RsaSignWithSha256([]byte(data), prvKey) //data  字符串。prvkey是私钥 生成签名 签名作为企业识别码
// RsaVerySignWithSha256([]byte(data), signData, pubKey) //检查签名是否正确
// ciphertext := RsaEncrypt([]byte(data), pubKey) 加密 hex.EncodeToString(ciphertext) 加密后到数据
// RsaDecrypt(ciphertext, prvKey) 解密后的数据 string(sourceData)

//解密 提供私钥植入代码 签名通过配置 加密数据通过配置实现
//续签 提供签名 加密数据
